# -*- coding: utf-8 -*-
import time
import re
import json
import os

from datetime import datetime
from config import (
    ItemIDs, GumpIDs, OrderBooks, NPCs, RuneBooks,
    VALUABLE_ORDER_COMBINATIONS, Bounds
)                                                       
from uo_order import UOOrder
from uo_items import UOItems
from uo_player import UOPlayer
from uo_mobiles import UOMobiles
from uo_orders import UOOrders

# Load user configuration
config_path = os.path.join(os.path.dirname(__file__), "user_config.json")
with open(config_path, "r", encoding="utf-8") as f:
    user_cfg = json.load(f)

TRASH_LOCATIONS = user_cfg["TRASH_LOCATIONS"]
BANK_LOCATIONS = user_cfg["BANK_LOCATIONS"]
HOME_LOCATIONS = user_cfg["HOME_LOCATIONS"]
BLACKSMITH_LOCATIONS = user_cfg["BLACKSMITH_LOCATIONS"]
BLACKSMITH_NPCS = user_cfg["BLACKSMITH_NPCS"]

# Items that need to be stored in bank during order delivery
ITEMS_TO_STORE_IN_BANK = [
    0x0EED,  # Gold Coin Item ID
    0x14F0,  # Bank Check Item ID
    0x1006   # Powder of Fortification Item ID
]

def do_deliver_orders():
    """Complete order delivery workflow for blacksmith orders.
    
    This function implements a complete workflow for managing and delivering blacksmith orders:
    
    1. Resource Initialization:
       - Find completed orders book (BS_DONE)
       - Find pending orders book (BS_NEW)
       - Find runestone book (BS_Runebook)
    
    2. Main Processing Loop:
       a. 2.1 背包状态检查与清理（循环开始）
          - Check if backpack needs cleaning (over 90% items or weight)
          - If needed: Teleport to trash barrel location and clean trash
          - If needed: Teleport to bank location and store valuable items
       
       b. 2.2 传送操作（按需执行）
          - Teleport to blacksmith shop locations
          - Find blacksmith NPC at each location
          - Request new orders from NPC
       
       c. 2.3 订单处理（无需传送）
          - Get orders in backpack and parse properties
          - Store incomplete orders in pending book
          - Deliver completed orders to NPC
          - Take new orders from completed book if needed
       
       d. 2.4 检查退出条件
          - Check if no orders in backpack and completed book
       
    3. Exit Conditions:
       - Missing required items (order books, runestone book)
       - Cannot find blacksmith NPC, trash barrel, or bank
       - No orders in backpack and completed book
       - Error during order delivery
    
    Returns:
        None
    """
    # Global variables for persistent objects
    orders_book_completed = None  # Will store the completed orders book once found
    orders_book_pending = None    # Will store the pending/unfinished orders book once found
    runestone_book = None        # Will store the runestone book object once found

    #print("=== Starting Order Delivery Workflow ===")
    print("=== 开始 ===")

    # 1. Initialize resources
    print("1.1. Finding completed orders book...")
    orders_book_completed = UOItems.FindByIDAndName(ItemIDs.ORDER_BOOK, Player.Backpack.Serial, OrderBooks.DONE)
    if not orders_book_completed:
        print("Missing completed orders book (BS_DONE)")
        return
    
    print("1.2. Finding pending orders book...")
    orders_book_pending = UOItems.FindByIDAndName(ItemIDs.ORDER_BOOK, Player.Backpack.Serial, OrderBooks.NEW)
    if not orders_book_pending:
        print("Missing pending orders book (BS_NEW)")
        return
    
    print("1.3. Finding runestone book...")
    runestone_book = UOItems.FindByIDAndName(ItemIDs.RUNESTONE_BOOK, Player.Backpack.Serial, RuneBooks.HOUSE)
    if not runestone_book:
        print("Missing runestone book (BS_Runebook)")
        return
    
    # 2. Main loop
    while True:
        # 2.1 背包状态检查与清理（循环开始）
        start_time = time.time()
        print("2.1. Checking backpack status...", end="")
        if(UOPlayer.IsBackpackOverLimit(0.5, 0.9)):
            # Teleport to trash barrel location and find barrel
            print("Backpack over limit, teleporting to trash barrel...")
            locations_to_try = TRASH_LOCATIONS  # Trash barrel locations from user config
            trash_teleport_success = False
            for location in locations_to_try:
                print(f"Using rune {location} for trash barrel...")
                success, message = UOPlayer.TeleportUsingRunebook(runestone_book, location)
                print(message)
                if success:
                    trash_teleport_success = True
                    break
            
            if not trash_teleport_success:
                print("Failed to teleport to trash barrel location")
                return
            
            print("Finding trash barrel...")
            trash_barrel = UOItems.FindNearestByID([ItemIDs.TRASH_BARREL, ItemIDs.TRASH_CHEST])
            if not trash_barrel:
                print("Missing trash barrel")
                return
            
            UOPlayer.MoveToTarget(trash_barrel, 2)
            UOItems.PutIntoTrashBarrel(trash_barrel)
            
            # Teleport to bank location and open bank
            print("Teleporting to bank...")
            locations_to_try = BANK_LOCATIONS  # Bank locations from user config
            bank_teleport_success = False
            for location in locations_to_try:
                print(f"Using rune {location} for bank...")
                success, message = UOPlayer.TeleportUsingRunebook(runestone_book, location)
                print(message)
                if success:
                    bank_teleport_success = True
                    break
            
            if not bank_teleport_success:
                print("Failed to teleport to bank location")
                return
            
            print("Opening bank...")
            UOItems.PutIntoBank(ITEMS_TO_STORE_IN_BANK)
        else:   
            Misc.Pause(2500)
        print(f"Backpack checked (took {time.time() - start_time:.3f} seconds)")

        # 2.2 传送操作（按需执行）
        print("2.2. Attempting to find a blacksmith...")
        
        # We will iterate through the blacksmith locations defined in user config.
        npc_blacksmith = None
        for rune_index in [0] + BLACKSMITH_LOCATIONS:
            print(f"--- Trying location (rune {rune_index}) ---")
            
            # Step 1: Teleport
            print(f"Teleporting...")
            success, message = UOPlayer.TeleportUsingRunebook(runestone_book, rune_index)
            print(message)
            
            if not success:
                continue

            # Step 2: Find any of the blacksmith NPCs at this location
            print(f"Looking for blacksmith NPCs...")
            Misc.Pause(1000) # Wait a moment for mobiles to load
            
            found_npc = UOMobiles.FindByName(BLACKSMITH_NPCS)
            if found_npc:
                print(f"Success! Found blacksmith '{found_npc.Name}'.")
                npc_blacksmith = found_npc
                break # Success, exit the location-finding loop
            else:
                print(f"No blacksmith NPCs found here. Trying next location.")

        # After trying all locations, check if we found a blacksmith
        if not npc_blacksmith:
            print("Could not find a blacksmith at any of the specified locations. Exiting workflow.")
            break # Exit the main `while True` loop

        # 2.3 订单处理（无需传送）
        # 2.3.1 Request orders from NPC
        start_time = time.time()
        print("2.3.1. Requesting order from npc...", end="")
        success, message = UOOrders.RequestFromNPC(npc_blacksmith)
        print(f"{message} (took {time.time() - start_time:.3f} seconds)")

        # 2.3.2 Get orders in backpack
        # Find all bulk order deeds in backpack and parse their properties
        print("2.3.2. Getting orders in backpack...", end="")
        start_time = time.time()
        
        orders_in_backpack: list[Item] = UOItems.FindAllByID(ItemIDs.ORDER, Player.Backpack.Serial)
        orders: list[UOOrder] = UOItems.ParseOrderProperties(orders_in_backpack)
        
        print(f"Found {len(orders)} orders (took {time.time() - start_time:.3f} seconds)")

        # 2.3.3 Process incomplete orders
        # Create a list of incomplete orders to process
        # We use a separate list to avoid modifying the original orders list during iteration
        print("2.3.3. Processing incomplete orders...", end="")
        start_time = time.time()
        
        incomplete_orders: list[UOOrder] = [order for order in orders if not order.is_completed]
        
        for order in incomplete_orders:
            UOOrders.PutOrderInBook(order.serial, orders_book_pending.Serial)
        print(f"Stored {len(incomplete_orders)} incomplete orders (took {time.time() - start_time:.3f} seconds)")

        # 2.3.4 Process completed orders
        # Find completed orders and deliver the first one to the blacksmith
        print("2.3.4. Processing completed orders...", end="")
        start_time = time.time()
        
        complete_orders: list[UOOrder] = [order for order in orders if order.is_completed]
        if complete_orders:  # If we have completed orders in backpack
            # Only process the first completed order
            success, message = UOOrders.DeliverOrder(complete_orders[0], npc_blacksmith)
            print(message)
            if not success:
                return
        else:
            # Try to get one order from completed book
            completed_book_count = int(UOItems.GetPropValue(orders_book_completed.Serial, "Deeds in book"))
            if completed_book_count > 0:
                success, message = UOOrders.TakeOrderFromBook(orders_book_completed.Serial)
                print(message)
                if not success:
                    return
        
        # 2.4 检查退出条件
        print("2.4. Checking if should exit loop...", end="")
        # Check if there are any orders in backpack
        orders_in_backpack = UOItems.BackpackCount(ItemIDs.ORDER)
        completed_book_count = int(UOItems.GetPropValue(orders_book_completed.Serial, "Deeds in book"))
        print(f"Orders in backpack: {orders_in_backpack}, Completed orders in book: {completed_book_count}")

        # Exit conditions:
        # 1. No orders in backpack 
        # 2. No orders in completed book 
        if (orders_in_backpack == 0 and completed_book_count == 0):  
            print("No more orders to process, exit while loop...")
            break

    # 3. Clean up backpack
    print("3.1. Cleaning up backpack...")
    # Teleport to trash barrel location and find barrel
    locations_to_try = TRASH_LOCATIONS  # Trash barrel locations from user config
    trash_teleport_success = False
    for location in locations_to_try:
        print(f"Using rune {location} for trash barrel...")
        success, message = UOPlayer.TeleportUsingRunebook(runestone_book, location)
        print(message)
        if success:
            trash_teleport_success = True
            break
    
    if not trash_teleport_success:
        print("Failed to teleport to trash barrel location")
        return
    
    print("Finding trash barrel...")
    trash_barrel = UOItems.FindNearestByID([ItemIDs.TRASH_BARREL, ItemIDs.TRASH_CHEST])
    if not trash_barrel:
        print("Missing trash barrel")
        return
    
    UOPlayer.MoveToTarget(trash_barrel, 1)
    UOItems.PutIntoTrashBarrel(trash_barrel)
    
    # Teleport to bank location and open bank
    print("3.2. Teleporting to bank...")
    locations_to_try = BANK_LOCATIONS  # Bank locations from user config
    bank_teleport_success = False
    for location in locations_to_try:
        print(f"Using rune {location} for bank...")
        success, message = UOPlayer.TeleportUsingRunebook(runestone_book, location)
        print(message)
        if success:
            bank_teleport_success = True
            break
    
    if not bank_teleport_success:
        print("Failed to teleport to bank location")
        return
    
    print("Opening bank...")
    UOItems.PutIntoBank(ITEMS_TO_STORE_IN_BANK)
    
    # 3.3. Teleport back to home
    print("3.3. Teleporting back to home...")
    locations_to_try = HOME_LOCATIONS  # Home locations from user config
    for location in locations_to_try:
        success, message = UOPlayer.TeleportUsingRunebook(runestone_book, location)
        if success:
            break

    print("=== Order Delivery Workflow Complete ===")

    
